//#include "GL/glew.h"
#include "GL/gl.h"
#include "GL/glut.h"
#include "FreeImage.h"
#include <cmath>
#include <iostream>
#include <string>
#include <map>
#include <cstdlib>
#include "demo.h"
#include "planet.h"
#include <stdio.h>
using namespace std;

extern long frameclock;

const double PAI=3.14159265;

double radiu, angle;
double ax, ay, aa;
double rx,ry,rcolor;
double daa=1.2;
double dtor=1.2;
double length=4.0;
double eyex = 0.0;
double eyey = 0.0;
double eyez = 0.0;

int frameRendered = 0;
int curFPS = 0;

GLenum drawFillMode=GL_FILL;
GLuint thelistnum;
GLuint textureNUM;

enum SCENE{NONE, CAMBER, SOLARY, LUNA, CORKSCREW, GEARS};
SCENE nowScene=GEARS;

void showScenInf()
{
	void *font = GLUT_BITMAP_TIMES_ROMAN_10;//glutBitmapTimesRoman24;
	glPushAttrib(GL_ALL_ATTRIB_BITS);
	glDisable(GL_LIGHTING);
	glDisable(GL_BLEND);
	glDisable(GL_TEXTURE_2D);
	glDisable(GL_DEPTH_TEST);

	glMatrixMode(GL_PROJECTION);
	glPushMatrix();
	glLoadIdentity();
	glMatrixMode(GL_MODELVIEW);
	glPushMatrix();
	glLoadIdentity();
	gluOrtho2D(0.0, 800.0, 0.0, 600.0);

	glColor3f(1.0f,0.0f,1.0f);

	char fpsbuffer[]="       \0";

	sprintf(fpsbuffer,"%d",curFPS);

	glRasterPos3f(10.0f,540.0f,0.0f);
	glutBitmapCharacter(font, ('F'));
	glutBitmapCharacter(font, ('P'));
	glutBitmapCharacter(font, ('S'));
	glutBitmapCharacter(font, (':'));
	glutBitmapCharacter(font, (' '));
	glutBitmapCharacter(font, (fpsbuffer[0]));
	glutBitmapCharacter(font, (fpsbuffer[1]));
	glutBitmapCharacter(font, (fpsbuffer[2]));
	glutBitmapCharacter(font, (fpsbuffer[3]));
	glutBitmapCharacter(font, (fpsbuffer[4]));
	glutBitmapCharacter(font, (fpsbuffer[5]));
	glutBitmapCharacter(font, ('H'));
	glutBitmapCharacter(font, ('z'));

	char seyex[18];
	sprintf(seyex,"%3.4f", eyex);

	glRasterPos3f(10.0,525.0f,0.0f);
	glutBitmapCharacter(font, ('e'));
	glutBitmapCharacter(font, ('y'));
	glutBitmapCharacter(font, ('e'));
	glutBitmapCharacter(font, ('x'));
	glutBitmapCharacter(font, (' '));
	glutBitmapCharacter(font, (seyex[0]));
	glutBitmapCharacter(font, (seyex[1]));
	glutBitmapCharacter(font, (seyex[2]));
	glutBitmapCharacter(font, (seyex[3]));
	glutBitmapCharacter(font, (seyex[4]));
	glutBitmapCharacter(font, (seyex[5]));
	glutBitmapCharacter(font, (seyex[6]));
	glutBitmapCharacter(font, (seyex[7]));	

	char seyey[18];
	sprintf(seyey,"%3.4f", eyey);

	glRasterPos3f(10.0f,510.0f,0.0f);
	glutBitmapCharacter(font, ('e'));
	glutBitmapCharacter(font, ('y'));
	glutBitmapCharacter(font, ('e'));
	glutBitmapCharacter(font, ('y'));
	glutBitmapCharacter(font, (' '));
	glutBitmapCharacter(font, (seyey[0]));
	glutBitmapCharacter(font, (seyey[1]));
	glutBitmapCharacter(font, (seyey[2]));
	glutBitmapCharacter(font, (seyey[3]));
	glutBitmapCharacter(font, (seyey[4]));
	glutBitmapCharacter(font, (seyey[5]));
	glutBitmapCharacter(font, (seyey[6]));
	glutBitmapCharacter(font, (seyey[7]));

	char seyez[18];
	sprintf(seyez,"%3.4f", eyez);

	glRasterPos3f(10.0f,495.0f,0.0f);
	glutBitmapCharacter(font, ('e'));
	glutBitmapCharacter(font, ('y'));
	glutBitmapCharacter(font, ('e'));
	glutBitmapCharacter(font, ('z'));
	glutBitmapCharacter(font, (' '));
	glutBitmapCharacter(font, (seyez[0]));
	glutBitmapCharacter(font, (seyez[1]));
	glutBitmapCharacter(font, (seyez[2]));
	glutBitmapCharacter(font, (seyez[3]));
	glutBitmapCharacter(font, (seyez[4]));
	glutBitmapCharacter(font, (seyez[5]));
	glutBitmapCharacter(font, (seyez[6]));
	glutBitmapCharacter(font, (seyez[7]));

	glPopMatrix();
	glMatrixMode(GL_PROJECTION);
	glPopMatrix();
	glMatrixMode(GL_MODELVIEW);
	
	glPopAttrib();
}

void display()
{	
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	if(nowScene == GEARS)
	{
		geardemo();
	}
	if(nowScene == CORKSCREW)
	{
		newdemo();
	}
	if(nowScene == CAMBER)
	{
		demo11();
		//newdemo();
	}
	if(nowScene == SOLARY)
	{
		solaryDraw();
	}
	if(nowScene == LUNA)
	{
		lunaDraw();
	}

	showScenInf();

	++frameRendered;
	usleep(1);
	glutSwapBuffers();
}

void init();
void initSolary();
void initLuna();

void farcall_keyboard(unsigned char key, int x, int y)
{
	if(key == 27)			//esc
	{
		exit(1);
		//PostQuitMessage(0);
	}

	if(key == '1')
	{
		if(nowScene != CAMBER)
		{
			nowScene = CAMBER;
			init();
			return;
		}
	}
	if(key == '2')
	{
		if(nowScene != SOLARY)
		{
			nowScene = SOLARY;
			initSolary();
			return;
		}
	}
	if(key == '3')
	{
		if(nowScene != LUNA)
		{
			nowScene = LUNA;
			initLuna();
			return;
		}
	}
	if(key == '4')
	{
		if(nowScene != CORKSCREW)
		{
			nowScene = CORKSCREW;
			init();
			return;
		}
	}
	if(key == '5')
	{
		if(nowScene != GEARS)
		{
			nowScene = GEARS;
			init();
			return;
		}
	}
	if(key == 'n')
	{
		length *= 0.95;
	}
	if(key == 'f')
	{
		length *= 1.05;
	}
	if(key=='l')
	{
		dtor -= 0.05;
	}
	if(key=='r')
	{
		dtor += 0.05;
	}
	if(key=='u')
	{
		daa -= 0.05;
	}		
	if(key=='d')
	{
		daa += 0.05;
	}
	if(key=='m')
	{
		if(drawFillMode == GL_FILL)
		{
			drawFillMode = GL_LINE;
		}
		else if(drawFillMode == GL_LINE)
		{
			drawFillMode = GL_POINT;
		}		
		else
		{
			drawFillMode = GL_FILL;
		}		

		glPolygonMode(GL_FRONT_AND_BACK,drawFillMode);
	}			
	//cout<<endl<<"len="<<length<<"\tdaa="<<daa<<"\tdtor="<<dtor;
	eyex = sin(daa)*length*cos(dtor);
	eyey = sin(daa)*length*sin(dtor);
	eyez = cos(daa)*length;

	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	gluLookAt(eyex,eyey,eyez,	
		0.0, 0.0, 0.0,	
		0.0, 0.0, 1.0);
}

int mouseFromx=0;
int mouseFromy=0;
bool isLeftDrag=true;

void farcall_mousedrag(int x, int y)
{
	double tdtor;
	double tdaa;
	double tlength;
	if(isLeftDrag)
	{
		tdtor = dtor-PAI*double(x-mouseFromx)/2000.0;
		tdaa = daa+PAI*double(y-mouseFromy)/2000.0;
		tlength = length;
	}
	else
	{
		tlength += length+double(y-mouseFromy)/200.0;
		tdtor = dtor;
		tdaa = daa;
	}

	//cout<<endl<<"tlen="<<tlength<<"\ttdaa="<<tdaa<<"\ttdtor="<<tdtor;
	eyex = sin(tdaa)*tlength*cos(tdtor);
	eyey = sin(tdaa)*tlength*sin(tdtor);
	eyez = cos(tdaa)*tlength;

	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	gluLookAt(eyex,eyey,eyez,	
		0.0, 0.0, 0.0,	
		0.0, 0.0, 1.0);

}

void farcall_mouse(int button, int state, int x, int y)
{
	if(GLUT_DOWN==state)
	{
		mouseFromx = x;
		mouseFromy = y;

		if(GLUT_LEFT_BUTTON==button)
		{
			isLeftDrag = true;
		}
		else
		{
			isLeftDrag = false;
		}		
	}
	else
	{
		if(GLUT_LEFT_BUTTON==button)
		{
			dtor = dtor-PAI*double(x-mouseFromx)/2000.0;
			daa = daa + PAI*double(y-mouseFromy)/2000.0;
		}
		else
		{
			length = length+double(y-mouseFromy)/200.0;
		}		
	}		
}

void texSet_luna()
{
	FreeImage_Initialise();

	FIBITMAP * dib = FreeImage_Load(FIF_JPEG, "luna.jpg", BMP_DEFAULT);

	FreeImage_GetWidth(dib),FreeImage_GetHeight(dib);

	dib = FreeImage_ConvertTo24Bits(dib);

	dib = FreeImage_Rescale(dib, 512, 512, FILTER_BILINEAR);

	BYTE *ptr = FreeImage_GetBits(dib);

	//glActiveTexture(GL_TEXTURE0);

	glGenTextures(1, &textureNUM);			// Create The Texture

	glBindTexture(GL_TEXTURE_2D, textureNUM);     	// Bind To The Texture ID
	
	glTexImage2D(GL_TEXTURE_2D, 
		0, 
		3, 
		FreeImage_GetWidth(dib), 
		FreeImage_GetHeight(dib), 
		0, 
		GL_BGR_EXT, 
		GL_UNSIGNED_BYTE, 
		ptr);

	FreeImage_Unload(dib);

	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);	

	glPixelStorei(GL_UNPACK_ALIGNMENT, 4); // Pixel Storage Mode (Word Alignment / 4 Bytes)
}
//*
void texSet_terrian()
{
	FreeImage_Initialise();

	FIBITMAP * dib = FreeImage_Load(FIF_BMP, "tex_.bmp", BMP_DEFAULT);

	FreeImage_GetWidth(dib),FreeImage_GetHeight(dib);

	dib = FreeImage_ConvertTo24Bits(dib);

	BYTE *ptr = FreeImage_GetBits(dib);

	//glActiveTexture(GL_TEXTURE0);

	glGenTextures(1, &textureNUM);			// Create The Texture

	glBindTexture(GL_TEXTURE_2D, textureNUM);     	// Bind To The Texture ID
	
	glTexImage2D(GL_TEXTURE_2D, 
		0, 
		3, 
		FreeImage_GetWidth(dib), 
		FreeImage_GetHeight(dib), 
		0, 
		GL_BGR_EXT, 
		GL_UNSIGNED_BYTE, 
		ptr);

	FreeImage_Unload(dib);

	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);	

	glPixelStorei(GL_UNPACK_ALIGNMENT, 4); // Pixel Storage Mode (Word Alignment / 4 Bytes)
}
//*/

void initSolary()
{
	glCullFace(GL_FRONT_AND_BACK);
	glShadeModel(GL_SMOOTH);

	glClearColor(1.0, 1.0, 1.0, 1.0);
	//glClearDepth(0.0f); 		// Depth Buffer Setup
	glDepthFunc(GL_LESS);
	glEnable(GL_DEPTH_TEST); 	// Enables Depth Testing
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glDisable(GL_BLEND);

	//glFrustum(1.0,1.0,		0.2,1.0,		0.0,10.0);		      
	//glRotatef(60.0, 1.0, 0.0, 0.0);
	//	
	//gluLookAt(1.0,	1.0,	1.0,	  0.0, 	0.0, 	0.0,	0.0,	0.0, 	1.0);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluPerspective(60.0, 1.0, 0.5, 20000.0);

	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	eyex = sin(daa)*length*cos(dtor);
	eyey = sin(daa)*length*sin(dtor);
	eyez = cos(daa)*length;

	gluLookAt(eyex, eyey, eyez,	
		0.0, 0.0, 0.0,	
		0.0, 0.0, 1.0);

	//texSet_terrian();
}

void initLuna()
{
	glCullFace(GL_FRONT_AND_BACK);
	glShadeModel(GL_SMOOTH);

	glClearColor(1.0, 1.0, 1.0, 1.0);
	//glClearDepth(0.0f); 		// Depth Buffer Setup
	glDepthFunc(GL_LESS);
	glEnable(GL_DEPTH_TEST); 	// Enables Depth Testing
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glDisable(GL_BLEND);

	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluPerspective(60.0, 1.0, 0.2, 20.0);

	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	eyex = sin(daa)*length*cos(dtor);
	eyey = sin(daa)*length*sin(dtor);
	eyez = cos(daa)*length;

	gluLookAt(eyex, eyey, eyez,	
		0.0, 0.0, 0.0,	
		0.0, 0.0, 1.0);

	texSet_luna();
}

void init()
{
	
	glCullFace(GL_FRONT_AND_BACK);
	glShadeModel(GL_SMOOTH);

	glClearColor(1.0, 1.0, 1.0, 1.0);
	//glClearDepth(0.0f); 		// Depth Buffer Setup
	glDepthFunc(GL_LESS);
	glEnable(GL_DEPTH_TEST); 	// Enables Depth Testing
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glDisable(GL_BLEND);

	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluPerspective(60.0, 1.0, 0.2, 20.0);

	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	eyex = sin(daa)*length*cos(dtor);
	eyey = sin(daa)*length*sin(dtor);
	eyez = cos(daa)*length;

	gluLookAt(eyex, eyey, eyez,	
		0.0, 0.0, 0.0,	
		0.0, 0.0, 1.0);

	texSet_terrian();
}

void computFrameRate(int value)
{
	curFPS = frameRendered*2;
	frameRendered=0;	
	glutTimerFunc(500, computFrameRate, 0);
}

int main()
{	
	//pcomputemain();
	//return 0;

	int   argc=0;
	char  *argv[10]; 

	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
	//glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_STENCIL | GLUT_ALPHA);
	
	glutInitWindowSize(800,640);
	glutInitWindowPosition(100,100);
	glutCreateWindow("zjn_openGL");

	if(nowScene == NONE)
	{
		nowScene = CAMBER;
		//nowScene = SOLARY;
	}
	if(nowScene == GEARS)
	{
		init();
	}
	if(nowScene == CAMBER)
	{
		init();
	}
	if(nowScene == SOLARY)
	{
		initSolary();
	}
	if(nowScene == LUNA)
	{
		initLuna();
	}
	
	//初始化GLSL环境
	//glewInit();
	//if (glewIsSupported("GL_VERSION_2_0"))
	//{
	//	cout<<"GL_VERSION_2_0 is support by your gpu"<<endl;
	//}	

	glutDisplayFunc(display);	

	glutIdleFunc(display);

	glutKeyboardFunc(farcall_keyboard);

	glutMouseFunc(farcall_mouse);

	glutMotionFunc(farcall_mousedrag);
	
	glutTimerFunc(500, computFrameRate, 0);

	glutMainLoop();
	
	return 0;
}
